<script>
import { deepClone } from '@/framework/utils/index'
import { handleTableData } from '@/framework/utils/getTableOptions'
import render from '@/framework/views/workflow/flowManage/flowFormDesign/components/render/render'
const ruleTrigger = {
  'el-input': 'blur',
  'el-input-number': '',
  'el-select': 'change',
  'el-radio-group': 'change',
  'el-checkbox-group': 'change',
  'el-cascader': 'change',
  'el-time-picker': 'change',
  'el-date-picker': 'change',
  'el-rate': 'change'
}
const setDefault = (scheme) => {
  const obj = {
    number: 0,
    slider: 0,
    rate: 0,
    select: scheme.multiple ? [] : '',
    cascader: scheme.multiple ? [] : '',
    checkbox: [],
    'date-range': [],
    'time-range': [],
    'dt-upload': []
  }
  return obj[scheme.__config__.tableColumnType] === undefined ? null : obj[scheme.__config__.tableColumnType]
}

const layouts = {
  dtTableDialogRender(h, scheme) {
    const config = scheme.__config__
    scheme.formModel = {}
    const rowProps = {}
    const tableCol = config.children.map(item => {
      rowProps[item.__vModel__] = '-'
      const obj = handleTableData(item)
      const resultRow = {
        prop: item.__vModel__,
        label: item.__config__.label,
        type: item.__config__.tableColumnType,
        show: true
      }
      return obj[item.__config__.tableColumnType] ? { ...resultRow, ...obj[item.__config__.tableColumnType] } : resultRow
    })
    scheme.__config__.tableOpts.tableCol = tableCol
    scheme.__config__.tableOpts.indexTableCol && (scheme.__config__.tableOpts.indexTableCol.index = scheme.__config__.orderNumber || true)
    scheme.__config__.tableOpts.operator = {
      width: 292,
      operatorBtn: [
        {
          'text': '编辑',
          size: 'mini',
          disabledChange: (row) => { return this.isDetail === true },
          click: (row, col, cellValue) => { return this.addRow('编辑', scheme, { row, col, cellValue }) }
        },
        {
          'text': '复制',
          size: 'mini',
          disabledChange: (row) => { return this.isDetail === true },
          click: (row, col, cellValue) => { return this.copyRow(scheme, { row, col, cellValue }) }
        },
        {
          'text': '移除',
          size: 'mini',
          type: 'danger',
          disabledChange: (row) => { return this.isDetail === true },
          click: (row, col, cellValue) => {
            return this.handleDelete(cellValue, scheme)
          }
        }
      ]
    }
    scheme.rowProps = rowProps
    const temp = {
      formBtns: true,
      formModel: `formData11`,
      formRef: `form${scheme.__config__.formId}`,
      formRules: 'rules',
      gutter: 15,
      labelPosition: 'right',
      labelWidth: 100,
      size: 'medium',
      span: 24,
      fields: config.children

    }
    const parseRef = `parse${scheme.__config__.formId}`
    return <el-col span={config.span}>
      <div class='labelName'>
        <span>{scheme.__config__.label}</span>
        <el-button size='mini' class='addBtn' type='primary' onClick={() => { this.addRow('添加', scheme, temp) }}>添加行</el-button>
      </div>
      <dt-table is-show-column={true} is-column-search={true} class='dtTableCon' table-opts={scheme.__config__.tableOpts} />
      <dt-dialog on={this.cancel(scheme)} title={this.tableDialog[scheme.__config__.formId].title} onComfirmBtn={() => { this.$refs[parseRef].submitForm() }} onCloseDialog={() => { this.closeDialog(temp, scheme) }} append-to-body={true} visible={this.tableDialog[scheme.__config__.formId].visible}>
        <div slot='content' class='dt-select-person-body'>
          {
            this.tableDialog[scheme.__config__.formId].visible
              ? <Parser ref={parseRef} form-conf={ temp} isFormTable={true} is-preview={true} onSubmit={(params) => {
                this.getTableForm(params, scheme, temp)
              }}/> : ''
          }
        </div>
      </dt-dialog>
    </el-col>
  },
  colFormItem(h, scheme) {
    const config = scheme.__config__
    // if (config.tableColumnType === 'select' || config.tableColumnType === 'radio') {
    //   if (config.defaultValue) {
    //     this.$set(config, 'defaultValue', parseInt(config.defaultValue))
    //   }
    // }
    // if (config.tableColumnType === 'cascader' || config.tableColumnType === 'checkbox') {
    //   if (config.defaultValue) {
    //     config.defaultValue = config.defaultValue.map(item => {
    //       return parseInt(item)
    //     })
    //   }
    // }
    const listeners = buildListeners.call(this, scheme)

    let labelWidth = config.labelWidth ? `${config.labelWidth}px` : null
    if (config.showLabel === false) labelWidth = '0'
    return (
      <el-col span={config.span}>
        <el-form-item label-width={labelWidth} prop={scheme.__vModel__}
          label={config.showLabel ? config.label : ''}>
          <render conf={scheme} on={listeners} />
        </el-form-item>
      </el-col>
    )
  },
  rowFormItem(h, scheme) {
    let child = renderChildren.apply(this, arguments)
    if (scheme.type === 'flex') {
      child = <el-row type={scheme.type} justify={scheme.justify} align={scheme.align}>
        {child}
      </el-row>
    }
    return (
      <el-col span={scheme.span}>
        <el-row gutter={scheme.gutter}>
          {child}
        </el-row>
      </el-col>
    )
  }
}

function renderFrom(h) {
  const { formConfCopy } = this
  return (
    <el-row gutter={formConfCopy.gutter}>
      <el-form
        size={formConfCopy.size}
        label-position={formConfCopy.labelPosition}
        disabled={formConfCopy.disabled}
        label-width={`${formConfCopy.labelWidth}px`}
        ref={formConfCopy.formRef}
        nativeOnSubmit={event => event.preventDefault()}
        // model不能直接赋值 https://github.com/vuejs/jsx/issues/49#issuecomment-472013664
        props={{ model: this[formConfCopy.formModel] }}
        rules={this[formConfCopy.formRules]}
      >
        {renderFormItem.call(this, h, formConfCopy.fields)}
        {!this.isPreview ? formConfCopy.formBtns && formBtns.call(this, h) : ''}
      </el-form>
    </el-row>
  )
}

function formBtns(h) {
  return <el-col>
    <el-form-item size='large'>
      <el-button type='primary' onClick={this.submitForm}>提交</el-button>
      <el-button onClick={this.resetForm}>重置</el-button>
    </el-form-item>
  </el-col>
}

// function isdtTableDialogRender(scheme) {
//   if (scheme.__config__.layout === 'dtTableDialogRender' && !this.tableDialog[scheme.__config__.formId]) {
//     this.$set(this.tableDialog, scheme.__config__.formId, {
//       visible: false,
//       title: '',
//       curIndex: 0
//     })
//   }
// }
function renderFormItem(h, elementList) {
  return elementList.map(scheme => {
    const config = scheme.__config__
    if (scheme.__config__.layout === 'dtTableDialogRender' && !this.tableDialog[scheme.__config__.formId]) {
      this.$set(this.tableDialog, scheme.__config__.formId, {
        visible: false,
        title: '',
        curIndex: 0
      })
    }
    // isdtTableDialogRender(scheme)
    const layout = layouts[config.layout]
    // if (layout) {
    //   return layout.call(this, h, scheme)
    // }
    if (config.layout === 'dtTableDialogRender' && !config.children.length) {
      return
    } else if (layout) {
      return layout.call(this, h, scheme)
    }
    throw new Error(`没有与${config.layout}匹配的layout`)
  })
}

function renderChildren(h, scheme) {
  const config = scheme.__config__
  if (!Array.isArray(config.children)) return null
  return renderFormItem.call(this, h, config.children)
}

function setValue(event, config, scheme) {
  this.$set(config, 'defaultValue', event)
  this.$set(this[this.formConf.formModel], scheme.__vModel__, event)
}

function buildListeners(scheme) {
  const config = scheme.__config__
  const methods = this.formConf.__methods__ || {}
  const listeners = {}

  // 给__methods__中的方法绑定this和event
  Object.keys(methods).forEach(key => {
    listeners[key] = event => methods[key].call(this, event)
  })
  // 响应 render.js 中的 vModel $emit('input', val)
  listeners.input = event => setValue.call(this, event, config, scheme)

  return listeners
}

export default {
  name: 'Parser',
  components: {
    render
  },
  provide: {
    showOptArr: []
  },
  props: {
    formConf: {
      type: Object,
      required: true
    },
    isPreview: { // 是否预览
      type: Boolean,
      default: false
    },
    isFormTable: {
      type: Boolean,
      default: false
    },
    isDetail: {
      type: Boolean,
      default: false
    }
  },
  data() {
    const data = {
      show: true,
      tableDialog: {},
      formConfCopy: this.isFormTable ? this.formConf : deepClone(this.formConf),
      [this.formConf.formModel]: {},
      [this.formConf.formRules]: {}
    }
    this.initFormData(data.formConfCopy.fields, data[this.formConf.formModel])
    this.buildRules(data.formConfCopy.fields, data[this.formConf.formRules])
    return data
  },
  methods: {
    cancel(scheme) {
      return { 'update:visible': value => { this.tableDialog[scheme.__config__.formId].visible = value } }
    },
    initFormData(componentList, formData) {
      componentList.forEach(cur => {
        const config = cur.__config__
        if (cur.__vModel__) formData[cur.__vModel__] = config.defaultValue
        if (config.children && config.tag !== 'dt-table') this.initFormData(config.children, formData)
      })
    },
    buildRules(componentList, rules) {
      componentList.forEach(cur => {
        const config = cur.__config__
        if (Array.isArray(config.regList)) {
          if (config.required) {
            const required = { required: config.required, message: cur.placeholder }
            if (Array.isArray(config.defaultValue)) {
              required.type = 'array'
              required.message = `请至少选择一个${config.label}`
            }
            required.message === undefined && (required.message = `${config.label}不能为空`)
            config.regList.push(required)
          }
          rules[cur.__vModel__] = config.regList.map(item => {
            item.pattern && (item.pattern = eval(item.pattern))
            item.trigger = ruleTrigger && ruleTrigger[config.tag]
            return item
          })
        }
        if (config.children) this.buildRules(config.children, rules)
      })
    },
    resetForm() {
      this.formConfCopy = deepClone(this.formConf)
      this.$refs[this.formConf.formRef].resetFields()
    },
    addRow(title, scheme, params) {
      this.tableDialog[scheme.__config__.formId] = {
        visible: true,
        title,
        curIndex: title === '编辑' ? params.cellValue : scheme.__config__.tableOpts.tableData.length
      }
      if (title === '编辑') {
        this.editSetValue(scheme.__config__.children, params.row)
      }
    },
    copyRow(scheme, params) {
      const { ...other } = params.row
      scheme.__config__.tableOpts.tableData.splice(params.cellValue, 0, JSON.parse(JSON.stringify(other)))
    },
    // 删除
    handleDelete(i, scheme) {
      this.$dtMessageBox({
        title: '提示',
        message: '是否确认移除第“' + (i + 1) + '”项?',
        type: 'warning'
      }).then(() => {
        scheme.__config__.tableOpts.tableData.splice(i, 1)
      })
    },
    closeDialog(temp, scheme) {
      // this.tableDialog.visible = false
      this.tableDialog[scheme.__config__.formId].visible = false
      this.clarData(temp)
    },
    clarData(temp) {
      temp && temp.fields.forEach(item => {
        item.__config__.defaultValue = setDefault(item)
      })
    },
    editSetValue(componentList, formData) {
      componentList.forEach(cur => {
        const config = cur.__config__
        // if (cur.__vModel__) config.defaultValue = formData[cur.__vModel__]
        if (cur.__vModel__) this.$set(config, 'defaultValue', formData[cur.__vModel__])
      })
    },
    getTableForm(params, scheme, temp) {
      scheme.__config__.tableOpts.tableData.splice(this.tableDialog[scheme.__config__.formId].curIndex, 1, JSON.parse(JSON.stringify(params.valData)))
      this.clarData(temp)
      // this.tableDialog.visible = false
      this.tableDialog[scheme.__config__.formId].visible = false
    },
    submitForm() {
      return this.$refs[this.formConf.formRef].validate(valid => {
        if (!valid) return false
        // 触发sumit事件
        // this.$emit('submit', this[this.formConf.formModel])
        const params = {
          formData: this.formConfCopy,
          valData: this[this.formConf.formModel]
        }
        this.$emit('submit', params)
        return true
      })
    },
    // 传值给父组件
    getData() {
      this.$emit('getData', this[this.formConf.formModel])
      // this.$emit('getData',this.formConfCopy)
    }
  },
  render(h) {
    return renderFrom.call(this, h)
  }
}
</script>
<style scoped lang="scss">
.addBtn{
    z-index: 1;
}
.labelName{
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-weight: 600;
  margin-bottom: -12px;
}
.dtTableCon{
  margin-bottom: 24px;
}
</style>
